home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 42
/
Amiga Format AFCD42 (Issue 126, Aug 1999).iso
/
-serious-
/
comms
/
other
/
slrn
/
slrn_src
/
src
/
nntp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-05-14
|
9KB
|
428 lines
/* Copyright (c) 1998 John E. Davis (davis@space.mit.edu)
*
* This file is part of slrn.
*
* Slrn is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* Slrn is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with Slrn; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "slrnfeat.h"
#include <stdio.h>
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <string.h>
#include <errno.h>
#include <slang.h>
#include "jdmacros.h"
#include "server.h"
#ifdef VMS
# include "vms.h"
#endif
int Slrn_Query_Reconnect = 1;
static Slrn_Server_Obj_Type NNTP_Server_Obj;
static Slrn_Post_Obj_Type NNTP_Post_Obj;
static NNTP_Type *NNTP_Server;
static int NNTP_Port = -1;
static char *NNTP_Server_Name;
/* If 1, abort. If -1, abort unless keyboard quit. */
static int _NNTP_Abort_On_Disconnection;
static void _nntp_connection_lost_hook (NNTP_Type *s)
{
if (_NNTP_Abort_On_Disconnection)
{
if ((_NNTP_Abort_On_Disconnection == -1) && SLKeyBoard_Quit)
return;
slrn_exit_error ("Server connection to %s lost. Cannot recover.",
s->host);
}
}
static int _nntp_interrupt_handler (void)
{
(void) slrn_handle_interrupts ();
if ((SLang_Error == USER_BREAK) || SLKeyBoard_Quit)
return -1;
return 0;
}
static void _nntp_reset (void)
{
NNTP_Type *s = NNTP_Server;
nntp_disconnect_server (s);
/* The next NNTP command will actually perform the reset. */
}
static void _nntp_close_server (void)
{
NNTP_Type *s = NNTP_Server;
NNTP_Server = NULL;
if (s != NULL) nntp_close_server (s);
}
static int _nntp_initialize_server (void)
{
NNTP_Authorization_Hook = slrn_get_authorization;
SLTCP_Interrupt_Hook = _nntp_interrupt_handler;
if (NNTP_Server != NULL)
nntp_close_server (NNTP_Server);
if (NULL == (NNTP_Server = nntp_open_server (NNTP_Server_Name, NNTP_Port)))
return -1;
if (-1 == nntp_has_cmd (NNTP_Server, "XOVER"))
{
_nntp_close_server ();
return -1;
}
if (NNTP_Server->can_xover == 0)
{
slrn_message_now ("Server %s does not implement the XOVER command.",
NNTP_Server->host);
NNTP_Server_Obj.sv_has_xover = 0;
}
else NNTP_Server_Obj.sv_has_xover = 1;
NNTP_Server->flags |= NNTP_RECONNECT_OK;
NNTP_Connection_Lost_Hook = _nntp_connection_lost_hook;
return 0;
}
static char *_nntp_read_line (char *buf, unsigned int len)
{
int status;
status = nntp_read_line (NNTP_Server, buf, len);
if (status == 1)
return buf;
if (status == 0)
{
_NNTP_Abort_On_Disconnection = 0;
return NULL;
}
/* Read fail or user break. Either way, we have to shut it down. */
_nntp_connection_lost_hook (NNTP_Server);
return NULL;
}
static int _nntp_head_cmd (int id, char *msgid, int *real_idp)
{
return nntp_head_cmd (NNTP_Server, id, msgid, real_idp);
}
static int _nntp_select_article (int n, char *msgid)
{
return nntp_article_cmd (NNTP_Server, n, msgid);
}
static int _nntp_select_group (char *grp, int *min, int *max)
{
return nntp_select_group (NNTP_Server, grp, min, max);
}
static int _nntp_put_server_cmd (char *cmd, char *buf, unsigned int len)
{
int code;
if (-1 != (code = nntp_server_cmd (NNTP_Server, cmd)))
{
strncpy (buf, NNTP_Server->rspbuf, len);
if (len) buf[len - 1] = 0;
}
return code;
}
static int _nntp_xpat_cmd (char *hdr, int rmin, int rmax, char *pat)
{
return nntp_xpat_cmd (NNTP_Server, hdr, rmin, rmax, pat);
}
static int _nntp_xhdr_cmd (char *hdr, int num,
char *buf, unsigned int buflen)
{
return nntp_xhdr_cmd (NNTP_Server, hdr, num, buf, buflen);
}
static int _nntp_xgtitle_cmd (char *pat)
{
return nntp_xgtitle_cmd (NNTP_Server, pat);
}
static int _nntp_has_cmd (char *cmd)
{
return nntp_has_cmd (NNTP_Server, cmd);
}
static int _nntp_list_newsgroups (void)
{
return nntp_list_newsgroups (NNTP_Server);
}
static int _nntp_list_active (void)
{
int code;
code = nntp_list_active_cmd (NNTP_Server);
if (OK_GROUPS == code)
_NNTP_Abort_On_Disconnection = 1;
return code;
}
static int _nntp_start_post (void)
{
/* Make sure we're connected to a server -- won't be the case the first
* time we post if we're reading news from a local spool. In this case
* a late connect is better as we don't bother the server until we need
* to.
*/
if (NNTP_Server == NULL)
{
if (-1 == _nntp_initialize_server ())
return -1;
}
return nntp_post_cmd (NNTP_Server);
}
static int _nntp_end_post (void)
{
int status;
status = nntp_end_post (NNTP_Server);
if (status == -1)
{
slrn_error ("Error writing to server.");
return -1;
}
if (NNTP_Server->code != OK_POSTED)
{
slrn_error ("Article rejected: %s", NNTP_Server->rspbuf);
return -1;
}
return 0;
}
static int _nntp_po_puts (char *buf)
{
char *b;
/* make sure \n --> \r\n */
b = buf;
while (NULL != (b = slrn_strchr (buf, '\n')))
{
unsigned int len;
len = (unsigned int) (b - buf);
if ((-1 == nntp_write_server (NNTP_Server, buf, len))
|| (-1 == nntp_write_server (NNTP_Server, "\r\n", 2)))
return -1;
buf = b + 1;
}
return nntp_fputs_server (NNTP_Server, buf);
}
static int _nntp_po_printf (char *fmt, ...)
{
va_list ap;
char buf[NNTP_BUFFER_SIZE];
va_start (ap, fmt);
vsprintf (buf, fmt, ap);
va_end (ap);
return _nntp_po_puts (buf);
}
static int _nntp_xover_cmd (int min, int max)
{
int status;
if (OK_XOVER == (status = nntp_xover_cmd (NNTP_Server, min, max)))
{
_NNTP_Abort_On_Disconnection = -1;
}
return status;
}
static int _nntp_next_cmd (int *id)
{
return nntp_next_cmd (NNTP_Server, id);
}
static int nntp_init_objects (void)
{
NNTP_Post_Obj.po_start = _nntp_start_post;
NNTP_Post_Obj.po_end = _nntp_end_post;
NNTP_Post_Obj.po_printf = _nntp_po_printf;
NNTP_Post_Obj.po_puts = _nntp_po_puts;
NNTP_Post_Obj.po_can_post = 1;
NNTP_Server_Obj.sv_select_group = _nntp_select_group;
NNTP_Server_Obj.sv_read_line = _nntp_read_line;
NNTP_Server_Obj.sv_close = _nntp_close_server;
NNTP_Server_Obj.sv_initialize = _nntp_initialize_server;
NNTP_Server_Obj.sv_select_article = _nntp_select_article;
NNTP_Server_Obj.sv_put_server_cmd = _nntp_put_server_cmd;
NNTP_Server_Obj.sv_xpat_cmd = _nntp_xpat_cmd;
NNTP_Server_Obj.sv_xhdr_command = _nntp_xhdr_cmd;
NNTP_Server_Obj.sv_xgtitle_cmd = _nntp_xgtitle_cmd;
NNTP_Server_Obj.sv_has_cmd = _nntp_has_cmd;
NNTP_Server_Obj.sv_list_newsgroups = _nntp_list_newsgroups;
NNTP_Server_Obj.sv_list_active = _nntp_list_active;
NNTP_Server_Obj.sv_has_xover = 0;
NNTP_Server_Obj.sv_nntp_xover = _nntp_xover_cmd;
NNTP_Server_Obj.sv_nntp_head = _nntp_head_cmd;
NNTP_Server_Obj.sv_nntp_next = _nntp_next_cmd;
NNTP_Server_Obj.sv_reset = _nntp_reset;
return 0;
}
static int _nntp_get_server_name (void)
{
char *host;
if (NULL == (host = NNTP_Server_Name))
{
host = nntp_get_server_name ();
if (host == NULL)
return -1;
}
NNTP_Server_Name = NNTP_Server_Obj.sv_name = slrn_safe_strmalloc (host);
return 0;
}
static int nntp_select_server_object (void)
{
if (NNTP_Server_Obj.sv_select_group == NULL)
nntp_init_objects ();
Slrn_Server_Obj = &NNTP_Server_Obj;
if (NNTP_Server_Obj.sv_name == NULL)
return _nntp_get_server_name ();
return 0;
}
static int nntp_select_post_object (void)
{
if (NNTP_Post_Obj.po_start == NULL)
nntp_init_objects ();
Slrn_Pos